Skip to main content

trash-cli — Terminal Trash (Safer Than rm) Safer Delete VPS

On servers, rm is fast—and unforgiving. trash-cli gives you a safety net by moving files to a Trash location (XDG / FreeDesktop Trash spec), keeping metadata like original path and deletion time so you can list and restore what you removed.

When to use trash-cli
  • Before editing/deleting critical files (wp-config.php, .htaccess)
  • When cleaning WordPress logs/cache/uploads but you still want an “undo”
  • In maintenance workflows where mistakes are expensive
Server reality check

Trash is still disk usage. If you trash large backups/media and never prune, your disk can fill up.

Prerequisites

  • Ubuntu/Debian (or similar Linux VPS)
  • SSH access
  • Common WordPress paths (examples):
    • /var/www/html/ → WP root
    • /var/www/html/wp-content/uploads/ → Media
    • /home/backups/ → Backups

Install & Verify

sudo apt update
sudo apt install -y trash-cli

Verify:

trash --version || trash-put --version

How It Works

trash-cli follows the desktop Trash spec (XDG/FreeDesktop). In practice:

  • “Deleting” becomes move to Trash
  • You can audit what you trashed
  • You can restore items to their original location
  • You can prune Trash by age
Where is the Trash stored?

By default (per spec), the user Trash is typically:

echo ~/.local/share/Trash

You’ll usually see subfolders like files/ and info/.

Not a backup system

Trash helps you recover from mistakes, but it’s not a real backup strategy. Use snapshots/backups for long-term safety.

Command Map

# Safer delete (move to Trash)
trash [FILES...] # often same as: trash-put [FILES...]

# Inspect
trash-list # list trashed items (original path + deletion date)

# Restore
trash-restore # interactive restore selection
trash-restore --overwrite # overwrite destination if needed

# Prune
trash-empty [DAYS] # empty all, or only items older than DAYS

# Permanently remove from Trash by pattern
trash-rm 'GLOB' # delete matching trashed items permanently
trash vs trash-put

On many systems, trash is a convenient wrapper/synonym for trash-put. If trash isn’t available, use trash-put.

Quick Decision Guide

GoalBest Command
--
Safer delete (keep an undo path)trash file_or_dir
See what’s currently in Trashtrash-list
Restore something you removedtrash-restore
Restore even if file exists alreadytrash-restore --overwrite
Keep Trash under control automaticallytrash-empty 30
Permanently purge only certain trashed filestrash-rm '*.sql'

Most Useful Moves (Ratings)

Move⭐ RatingWhy It Matters
-:--
Use trash instead of rm for risky deletes⭐⭐⭐⭐⭐Gives you an undo path on production-like systems
trash-restore⭐⭐⭐⭐⭐Brings back files without guesswork (interactive selection)
trash-empty N⭐⭐⭐⭐Simple retention policy (great with cron)
trash-list⭐⭐⭐⭐Fast audit trail of what you deleted
trash-rm⭐⭐⭐Targeted permanent purge (useful, but less frequent)

Best Practices

  • Prefer trash for anything you might want back.
  • Set a retention policy (example: keep 30 days).
  • Quote globs for trash-rm so your shell doesn’t expand them early.
  • Avoid “blind” cleanup in production paths—always inspect first (trash-list, ls, du -sh).
Don’t blindly alias rm to trash

They are not identical in behavior and expectations (especially in scripts). If you must, use a safer wrapper that warns you rather than silently changing semantics.

Add a daily retention job (cron)

# Purge items older than 30 days, daily
(crontab -l 2>/dev/null; echo "@daily $(command -v trash-empty) 30") | crontab -

Troubleshooting

ProblemLikely CauseFix
----
trash: command not foundNot installed or PATH missingInstall via APT/pipx/pip; ensure ~/.local/bin is in PATH
Can’t restore (name collision)File already exists at destinationUse trash-restore --overwrite
“Where did my files go?”Looking in wrong locationCheck ~/.local/share/Trash (user Trash)
Disk still full after “deleting”Trash not prunedRun trash-empty (or trash-empty 30)
trash-rm deletes nothingShell expanded glob before commandQuote pattern: trash-rm '*.log'

Cheat Sheet

# Safe delete
trash foo.txt
trash dir/

# Audit
trash-list

# Restore
trash-restore
trash-restore --overwrite

# Retention / prune
trash-empty # empty all trash
trash-empty 30 # empty items older than 30 days
trash-rm '*.sql' # permanently purge matching trashed items

# Trash location (typical)
echo ~/.local/share/Trash

Worked Examples (Max 15)

Assumption

WordPress root is /var/www/html.

Safely delete a WordPress debug log

trash /var/www/html/wp-content/debug.log

Safely move old Nginx logs to Trash

trash /var/log/nginx/*.log

List trashed items (page through)

trash-list | less

Restore a mistakenly deleted wp-config.php

trash-restore

Restore and overwrite an existing placeholder

trash-restore --overwrite

Empty items older than 7 days

trash-empty 7

Empty Trash completely (cleanup event)

trash-empty

Permanently remove only .sql dumps from Trash

trash-rm '*.sql'

Automate 30-day retention (cron)

(crontab -l 2>/dev/null; echo "@daily $(command -v trash-empty) 30") | crontab -

Trash multiple paths including directories

trash /home/backups/*.tar.gz /var/www/html/wp-content/cache

Confirm Trash location

echo ~/.local/share/Trash

Find a trashed upload quickly (ripgrep)

trash-list | rg -n 'uploads/.*\.jpg$'

Dry-review before permanent purge

trash-list | grep '\.log$'

(Then decide whether to run trash-rm '*.log'.)

Simple cleanup ritual

trash /home/backups/*.old && trash-empty 14

One-liner: find an entry, feed index into restore (advanced)

idx=$(trash-list | nl -ba | grep 'wp-content/uploads/logo' | awk '{print $1; exit}')
trash-restore <<< "$idx"
Advanced example

This relies on interactive restore behavior and the list ordering. Use it only if you understand what it’s doing.

Mini Quiz

  1. Which command moves files to Trash, and which command lists what’s inside?
  2. How do you restore a file when the destination already exists?
  3. What does trash-empty 30 do?
  4. Where is the home Trash directory typically stored?
  5. Why is aliasing rm to trash discouraged?